﻿using TestingConcurrencyBenchmark.Benchmarks.BenchmarkTests;
using TestingConcurrencyBenchmark.ProblemFactories;

namespace TestingConcurrencyBenchmark.Benchmarks
{
    /// <summary>
    /// An abstract benchmark class that's responsible for making sure the right benchmark test is created
    /// It's generic to ensure typesafety
    /// </summary>
    /// <typeparam name="TSolution">The type of solution the abstractbenchmark is working with</typeparam>
    public abstract class AbstractBenchmark<TSolution>
    {
        /// <summary>
        /// A problemfactory to manufacture the right solution
        /// </summary>
        private readonly IProblemFactory<TSolution> _problemFactory;

        /// <summary>
        /// Creates a new Abstractbenchmark
        /// Sets the problemfactory to be the supplied problemfactory
        ///     | new._problemFactory = problemFactory
        /// </summary>
        /// <param name="problemFactory">A problemfactory to manufacture the right solution</param>
        protected AbstractBenchmark(IProblemFactory<TSolution> problemFactory)
        {
            _problemFactory = problemFactory;
        }

        /// <summary>
        /// Creates a test that should pass
        /// </summary>
        /// <returns>A benchmarktest on a solution</returns>
        public BenchmarkTest<TSolution> CreatePassingTest()
        {
            return CreateBenchmarkTest(_problemFactory.GetSolution());
        }

        /// <summary>
        /// Creates a test containing a deadlock
        /// </summary>
        /// <returns>A benchmarktest on a solution with a deadlock</returns>
        public BenchmarkTest<TSolution> CreateTestWithDeadlock()
        {
            return CreateBenchmarkTest(_problemFactory.GetSolutionWithDeadlock());
        }

        /// <summary>
        /// Creates a test containing a racecondition
        /// </summary>
        /// <returns>A benchmarktest on a solution with a racecondition</returns>
        public BenchmarkTest<TSolution> CreateTestWithRaceCondition()
        {
            return CreateBenchmarkTest(_problemFactory.GetSolutionWithRaceCondition());
        }

        /// <summary>
        /// Creates a test containing a datarace
        /// </summary>
        /// <returns>A benchmarktest on a solution with a datarace</returns>
        public BenchmarkTest<TSolution> CreateTestWithDatarace()
        {
            return CreateBenchmarkTest(_problemFactory.GetSolutionWithDatarace());
        }

        /// <summary>
        /// A method to create a new BenchmarkTest
        /// </summary>
        /// <param name="solution">The solution to base the BenchmarkTest on</param>
        /// <returns>the created BenchmarkTest</returns>
        protected abstract BenchmarkTest<TSolution> CreateBenchmarkTest(TSolution solution);
    }
}